home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / SMALLTAL / CONVERSI.ON_ < prev    next >
Text File  |  1990-07-16  |  8KB  |  243 lines

  1. The following file-in supports the reading and writing of Smalltalk Forms
  2. (here wrapped up in what I call an IconImage - a simple way of naming a Form)
  3. into the Portable Bitmap file format.  This format (copyrighted by Jef Poskanzer)
  4. is a lowest-common denominator allowing bitmap images to be sent over the
  5. mail, and converted between a whole variety of different formats including
  6. PICT, GIF, MacPaint, Sun Icons, Postscript, ASCII, etc.  I wrote this utility
  7. to make use of the Sun icon collection but have found it useful in taking
  8. images over from my Macintosh as well.  I hope you find it useful.  Any comments
  9. on the code (yes I know its a bit messy!) are welcome.
  10.  
  11. BTW, PBM is a public domain utility available on (at least) a variety of
  12. UNIX platforms.   The following piece of code is perhaps not as lenient
  13. of dodgy input as Poskanzer would like!
  14.  
  15. Cheers,
  16.    Kevin
  17.  
  18. -----------------------   C U T     H E R E   ----------------------
  19.  
  20.  
  21. 'From Objectworks for Smalltalk-80(tm), Version 2.5 of 29 July 1989 
  22. on 14 May 1990 at 6:25:56 pm'!
  23.  
  24. Object subclass: #IconImage
  25.         instanceVariableNames: 'name form '
  26.         classVariableNames: ''
  27.         poolDictionaries: ''
  28.         category: 'Icon-Browsing'!
  29. IconImage comment:
  30. 'I represent a named graphical image.  My instance variables
  31. hold my name and the Form that is my graphical representation.
  32. I support loading and saving using the Portable Bitmap format
  33. and thereby onto other graphical formats via the many conversion
  34. tools available in the PBM library.
  35.  
  36. The Portable Bitmap facility is copyright (c) 1988 by Jef Poskanzer.'!
  37.  
  38.  
  39. !IconImage methodsFor: 'accessing'!
  40.  
  41. form
  42.         ^form!
  43.  
  44. form: aForm
  45.         form := aForm.!
  46.  
  47. name
  48.         ^name!
  49.  
  50. name: aString
  51.         name := aString.! !
  52.  
  53. !IconImage methodsFor: 'file-in/out'!
  54.  
  55. writePBMfile: fileName
  56.         "Saves the receiver on the file fileName in Portable Bitmap format.
  57.         See the class method pbmSyntax for details of the format."
  58.         
  59.         | aStream bitMask wordCount bitCount bitsOnLine |
  60.  
  61.         aStream := fileName asFilename writeStream.
  62.         aStream nextPutAll: 'P1'; cr.
  63.         aStream nextPutAll: '#  Converted from Smalltalk Form on '.
  64.         aStream nextPutAll: Date today printString.
  65.         aStream nextPutAll: ' at ', Time now printString.
  66.         aStream cr.
  67.         aStream nextPutAll: self form width printString.
  68.         aStream space.
  69.         aStream nextPutAll: self form height printString.
  70.         aStream cr.
  71.  
  72.         bitMask := Array new: 16.
  73.         1 to: 16 do: [:k | bitMask at: k put: (1 bitShift: (k-1))].
  74.  
  75.         wordCount := self form width + 15 // 16 * self form height.
  76.  
  77.         "The following two counters are used to ensure that newlines are
  78.         forced on the stream after every 70 characters and after every
  79.         row has been completed (unless the row is shorter than 70 chars)."
  80.         
  81.         bitsOnLine := bitCount := 0.
  82.  
  83.         1 to: wordCount do: [:index |
  84.                 | endOfRow word bitNum bit |
  85.  
  86.                 word := self form bitsWordAt: index.
  87.                 bitNum := 16.
  88.                 endOfRow := false.
  89.                 [bitNum = 0 or: [endOfRow]] whileFalse: [
  90.                         bit := word bitAnd: (bitMask at: bitNum).
  91.                         aStream nextPut: (bit = 0 ifTrue: [$0] ifFalse: [$1]).
  92.                         bitsOnLine := bitsOnLine + 1.
  93.                         bitsOnLine > 70 ifTrue: [
  94.                                 aStream cr.
  95.                                 bitsOnLine := 0.
  96.                         ].
  97.                         bitNum := bitNum - 1.
  98.                         endOfRow := (bitCount := bitCount + 1) = self form width.
  99.                 ].
  100.                 endOfRow ifTrue: [
  101.                         aStream cr.
  102.                         bitCount := bitsOnLine := 0.
  103.                 ].
  104.         ].
  105.         aStream close.! !
  106.  
  107. !IconImage methodsFor: 'initialisation'!
  108.  
  109. initialize
  110.         self name: 'an Image'.
  111.         self form: nil.! !
  112. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  113.  
  114. IconImage class
  115.         instanceVariableNames: ''!
  116.  
  117.  
  118. !IconImage class methodsFor: 'instance creation'!
  119.  
  120. new
  121.         ^super new initialize!
  122.  
  123. pbmSyntax
  124.         "- A 'magic number' for identifying the  file  type.   A  pbm
  125.        file's magic number is the two characters 'P1'.
  126.  
  127.      - Whitespace (blanks, TABs, CRs, LFs).
  128.  
  129.      - A width, formatted as ASCII characters in decimal.
  130.  
  131.      - Whitespace.
  132.  
  133.      - A height, again in ASCII decimal.
  134.  
  135.      - Whitespace.
  136.  
  137.      - Width * height bits, each either '1' or '0',  starting  at
  138.        the  top-left  corner  of  the bitmap, proceding in normal
  139.        English reading order.
  140.  
  141.      - The character '1' means black, '0' means white.
  142.  
  143.      - Whitespace in the bits section is ignored.
  144.  
  145.      - Characters from a '#' to the next end-of-line are  ignored
  146.        (comments).
  147.  
  148.      - No line may be longer than 70 characters."!
  149.  
  150. readImageFromPBMFile: fileName
  151.         "Answer an instance of IconImage initialized from a Portable Bit Map
  152.         file.  The expected format of the file is in the method
  153.         IconImage class>pbmSyntax."
  154.  
  155.         | aFile aStream width height bits form bitMask index shift image |
  156.  
  157.         aFile := fileName asFilename.
  158.         aFile exists ifFalse: [^nil].
  159.         aStream := aFile readStream.
  160.  
  161.         (aStream peek = $P) 
  162.                 ifFalse: [self error: 'Invalid magic number'] 
  163.                 ifTrue: [aStream next].
  164.  
  165.         (aStream peek = $1) 
  166.                 ifFalse: [self error: 'Invalid magic number'] 
  167.                 ifTrue: [aStream next].
  168.  
  169.         self skipPBMJunkOn: aStream.
  170.         width := Integer readFrom: aStream.
  171.         width > 0 ifFalse: [self error: 'Invalid width'].
  172.  
  173.         self skipPBMJunkOn: aStream.
  174.         height := Integer readFrom: aStream.
  175.         height > 0 ifFalse: [self error: 'Invalid height'].
  176.         bits := WordArray new: (width + 15 // 16 * height).
  177.         form := Form new extent: width@height.
  178.  
  179.         "Initialize an array of sixteen 16-bit numbers each with a single
  180.         unique bit set corresponding to a power of two.  This will simplify
  181.         the setting of of pixel values within a compressed word."
  182.  
  183.         bitMask := Array new: 16.
  184.         1 to: 16 do: [:k | bitMask at: k put: (1 bitShift: (k-1))].
  185.  
  186.         index := 1.
  187.  
  188.         1 to: height do: [:y | | word |
  189.                 shift := 16.
  190.                 word := 0.
  191.  
  192.                 1 to: width do: [:x | 
  193.                         self skipPBMJunkOn: aStream.
  194.                         aStream atEnd ifTrue: [self error: 'Unexpected End-of-file'].
  195.  
  196.                         aStream next = $1 
  197.                                 ifTrue: [word := word bitOr: (bitMask at: shift)].
  198.  
  199.                         shift := shift - 1.
  200.                         shift = 0 ifTrue: [ "End of the current word?"
  201.                                 bits at: index put: word.
  202.                                 index := index + 1.
  203.                                 shift := 16.
  204.                                 word := 0.
  205.                         ].
  206.                 ].
  207.                 shift < 16 ifTrue: [ "A partly filled words needs to be saved."
  208.                         bits at: index put: word.
  209.                         index := index + 1.
  210.                 ].
  211.         ].
  212.         form bits: bits.
  213.         aStream close.
  214.         image := self new form: form.
  215.         image name: fileName.
  216.         ^image! !
  217.  
  218. !IconImage class methodsFor: 'parsing utilities'!
  219.  
  220. skipPBMJunkOn: aStream
  221.         "This method removes any superfluous characters 
  222.         from the input stream."
  223.  
  224.         | char |
  225.  
  226.         [char := aStream peek.
  227.          char = $# ifTrue: ["Start of a comment.  Skip to end-of-line."
  228.                 | foundNL |
  229.  
  230.                 foundNL := (aStream skipUpTo: Character cr) notNil.
  231.                 foundNL ifFalse: ["Must be EOF"  ^self].
  232.                 char := aStream peek.
  233.         ].
  234.         aStream atEnd not and: [char isSeparator]] whileTrue: [aStream next].! !
  235.  
  236.  
  237. -----------------------------   C U T    H E R E   --------------------
  238. -- 
  239. Email:   kww@uk.ac.glasgow.cs  (JANET)
  240.          kww%cs.glasgow.ac.uk@nsfnet-relay.ac.uk  (INTERNET)
  241. Address: Dept. of Computing Science,  University of Glasgow,
  242.          17 Lilybank Gardens,  Glasgow,  United Kingdom.  G12 8QQ
  243.